package top.jiangqiang.qianyi.common.base.model.response;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import top.jiangqiang.qianyi.common.base.http.BaseStatus;
import top.jiangqiang.qianyi.common.base.http.ErrorStatus;
import top.jiangqiang.qianyi.common.base.http.SuccessStatus;
import top.jiangqiang.qianyi.common.constants.http.Success200Status;
import top.jiangqiang.qianyi.common.exception.BaseException;
import top.jiangqiang.qianyi.common.utils.JsonUtil;

import java.io.Serial;
import java.io.Serializable;

/**
 * @Date 2023/10/23 19:10
 * @Author Jiangqiang
 */
@Getter
@EqualsAndHashCode
@Slf4j
@Schema(description = "通用响应结构")
@NoArgsConstructor(force = true, access = AccessLevel.PRIVATE)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public final class Result<T> implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;

    @Schema(description = "业务状态码，2开头为成功，其余为失败")
    private final Integer code;

    @Schema(description = "响应信息，操作成功时可忽略此信息，操作失败时此信息为错误提示")
    private final String message;

    @Schema(description = "响应数据")
    private final T data;

    public static <T> Result<T> ok() {
        return build(Success200Status.OK, null);
    }

    public static <T> Result<T> ok(T data) {
        return build(Success200Status.OK, data);
    }

    public static <T> Result<T> ok(SuccessStatus successStatus) {
        return build(successStatus, null);
    }

    public static <T> Result<T> ok(SuccessStatus successStatus, T data) {
        return build(successStatus, data);
    }

    public static <T> Result<T> error(BaseException baseException) {
        return build(baseException.getBusinessCode(), baseException.getMessage(), null);
    }

    public static <T> Result<T> error(ErrorStatus errorStatus) {
        return build(errorStatus, null);
    }

    public static <T> Result<T> error(ErrorStatus errorStatus, String message) {
        return build(errorStatus, message, null);
    }

    public static <T> Result<T> error(ErrorStatus errorStatus, String message, T data) {
        return build(errorStatus, message, data);
    }

    /**
     * @param baseStatus 状态枚举
     * @param message    自定义消息提示
     * @param data       数据
     * @return 响应包装对象
     */
    private static <T> Result<T> build(BaseStatus baseStatus, String message, T data) {
        return build(baseStatus.getBusinessCode(), message, data);
    }

    /**
     * @param baseStatus 状态枚举
     * @param data       数据
     * @return 响应包装对象
     */
    private static <T> Result<T> build(BaseStatus baseStatus, T data) {
        return build(baseStatus.getBusinessCode(), baseStatus.getMessage(), data);
    }

    /**
     * @param businessCode 业务编码
     * @param message      消息提示
     * @param data         数据
     * @return 响应包装对象
     */
    private static <T> Result<T> build(Integer businessCode, String message, T data) {
        log.debug("businessCode={}, message={}, data={}", businessCode, message, JsonUtil.toJsonStr(data));
        return new Result<>(businessCode, message, data);
    }

    @Override
    public String toString() {
        return JsonUtil.toJsonStr(this);
    }
}